package wallpaper

import (
	"auto-wallpaper/lock"
	"auto-wallpaper/profile"
	"auto-wallpaper/resolver"
	"auto-wallpaper/util"
	"fmt"
	"golang.org/x/sys/windows/registry"
	"os"
	"strconv"
	"strings"
	"syscall"
	"time"
	"unicode/utf16"
	"unsafe"
)

// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947.aspx
const (
	spiGetDeskWallpaper = 0x0073
	spiSetDeskWallpaper = 0x0014

	uiParam = 0x0000

	spifUpdateINIFile = 0x01
	spifSendChange    = 0x02
)

// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947.aspx
var (
	user32               = syscall.NewLazyDLL("user32.dll")
	systemParametersInfo = user32.NewProc("SystemParametersInfoW")
)

func LoadImg() {
	imgChan := make(chan string)
	resolver.ResolveImg(imgChan)

	// 备份图片
	if profile.AppConfigSet.DeleteOld {
		util.MvFile(profile.AppConfigSet.BasePath, profile.AppConfigSet.Bak)
	}
	var files, _ = util.ListDir(profile.AppConfigSet.BasePath, "")
	go DownImg(imgChan)
	profile.Imgs = &files
}

// Get returns the current wallpaper.
func Get() (string, error) {
	// the maximum length of a windows path is 256 utf16 characters
	var filename [256]uint16
	systemParametersInfo.Call(
		uintptr(spiGetDeskWallpaper),
		uintptr(cap(filename)),
		// the memory address of the first byte of the array
		uintptr(unsafe.Pointer(&filename[0])),
		uintptr(0),
	)
	return strings.Trim(string(utf16.Decode(filename[:])), "\x00"), nil
}

// SetFromFile sets the wallpaper for the current user.
func SetFromFile(filename string) error {
	filenameUTF16, err := syscall.UTF16PtrFromString(filename)
	if err != nil {
		return err
	}

	systemParametersInfo.Call(
		uintptr(spiSetDeskWallpaper),
		uintptr(uiParam),
		uintptr(unsafe.Pointer(filenameUTF16)),
		uintptr(spifUpdateINIFile|spifSendChange),
	)
	return nil
}

// SetMode sets the wallpaper mode.
func SetMode() error {
	key, _, err := registry.CreateKey(registry.CURRENT_USER, "Control Panel\\Desktop", registry.SET_VALUE)
	if err != nil {
		return err
	}
	defer key.Close()

	err = key.SetStringValue("TileWallpaper", profile.AppConfigSet.Tile)
	if err != nil {
		return err
	}

	err = key.SetStringValue("WallpaperStyle", profile.AppConfigSet.Style)
	if err != nil {
		return err
	}

	// updates wallpaper
	path, err := Get()
	if err != nil {
		return err
	}

	return SetFromFile(path)
}

func getCacheDir() (string, error) {
	return os.TempDir(), nil
}

// 切换图片
func SwitchImg() {
	if profile.AppConfigSet.AutoSwitch {

		var temp = 0
		for {

			var add = Switch(temp)
			if add {
				temp = temp + 1
			}
		}
	}
}

func Switch(temp int) bool {
	lock.ImagePoolLock.RLock()
	defer lock.ImagePoolLock.RUnlock()
	if len(*profile.Imgs) == 0 {
		if profile.AppConfigSet.Rate > 0 {
			time.Sleep(time.Second * time.Duration(profile.AppConfigSet.Rate))
		}
		return false
	}

	temp = temp % len(*profile.Imgs)
	// 切换下一张
	// 存在切换失败 多调一次
	fmt.Println("切换下一张图片")
	go func() {
		lock.ImagePoolLock.RLock()
		path := (*profile.Imgs)[temp]
		defer lock.ImagePoolLock.RUnlock()
		go SetFromFile(path)
	}()
	if profile.AppConfigSet.Rate > 0 {
		time.Sleep(time.Second * time.Duration(profile.AppConfigSet.Rate))
	}
	return true
}

// DownImg 下载图片
func DownImg(imgUrlChan chan string) {
	//更新
	util.MakeDir(profile.AppConfigSet.BasePath)
	for {
		if imgUrlChan != nil {
			imgUrl, ok := <-imgUrlChan
			if ok {
				// 下载图片
				go func() {
					fileName := util.NameByUrl(imgUrl)
					filePath := profile.AppConfigSet.BasePath + "/" + fileName
					down, err := util.Down(profile.AppConfigSet.Cover, filePath, imgUrl, profile.AppConfigSet.DownSleep, nil, fileName)
					fmt.Printf("保存图片状态 : %v\n", down)
					if err != nil {
						fmt.Println(err)
					}
					lock.ImagePoolLock.Lock()
					*profile.Imgs, _ = util.ListDir(profile.AppConfigSet.BasePath, "")
					fmt.Println("更新文件 ： " + strconv.Itoa(len(*profile.Imgs)))
					lock.ImagePoolLock.Unlock()
				}()
			} else {
				break
			}
		}
	}
}
